package it.antonio.ilpizze.db.core;

import it.antonio.ilpizze.db.HashListIndex;
import it.antonio.ilpizze.db.Id;
import it.antonio.ilpizze.db.Indexes;
import it.antonio.ilpizze.db.core.fs.BtreeIndexFile;
import it.antonio.ilpizze.db.core.fs.HashIndexFile;
import it.antonio.ilpizze.db.core.perst.IdPerst;
import it.antonio.ilpizze.db.core.perst.ObjectPerst;
import it.antonio.ilpizze.db.index.btree.BTree;
import it.antonio.ilpizze.db.index.btree.file.FileBTree;
import it.antonio.ilpizze.db.index.hash.HashTable;
import it.antonio.ilpizze.db.index.hash.file.FileHashTable;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class IndexManager implements Indexes{
	
	private DbFileSystem dbFs;
	private TransactionManager txManager;
	private StatusManager statusManager;
	private LockManager lockManager;
	
	private Map<String, BtreeIndexFile> btreeFiles = new HashMap<String, BtreeIndexFile>();
	private Map<String, HashIndexFile> hashFiles = new HashMap<String, HashIndexFile>();

	public IndexManager(DbFileSystem dbFs, TransactionManager txManager, StatusManager statusManager, LockManager lockManager) {
		this.dbFs = dbFs;
		this.txManager = txManager;
		this.statusManager = statusManager;
		this.lockManager = lockManager;
	}

	public void loadIndices(){
		
		List<String> btrees =  dbFs.toOpenBtreeIndexes();
		for(String btreeProp: btrees){
			
			BtreeIndexFile btreeFile = dbFs.openBtreeIndexFile(btreeProp);
			btreeFiles.put(btreeProp, btreeFile);
		}
		
		List<String> hashes =  dbFs.toOpenHashIndexes();
		for(String hashProp: hashes){
			
			HashIndexFile hashFile = dbFs.openHashIndexFile(hashProp);
			hashFiles.put(hashProp, hashFile);
		}
		
	}
	
	@Override
	public <T> HashListIndex<T> hashList(String name) {
		statusManager.checkStatus(Status.OPEN, Status.TRANSACTION);
		lockManager.checkMultiThreadingRead();
		
		throw new UnsupportedOperationException();
	} 
	
	@Override
	public <T> FileHashIndex<T> hash(String name) {
		statusManager.checkStatus(Status.OPEN, Status.TRANSACTION);
		lockManager.checkMultiThreadingRead();
		
		HashIndexFile hashFile = hashFiles.get(name);
		if(hashFile == null){
			hashFile = dbFs.openHashIndexFile(name);
		}
		
		HashTable<T, Id> hTable = FileHashTable.getOrCreate(hashFile, 25, new ObjectPerst<T>(), new IdPerst());
		FileHashIndex<T> index = new FileHashIndex<T>(hTable, txManager, statusManager,lockManager);
		
		return index;

	}
	
	@Override
	public <T extends Comparable<T>> FileBtreeIndex<T> btree(String name) {
		statusManager.checkStatus(Status.OPEN, Status.TRANSACTION);
		lockManager.checkMultiThreadingRead();
		
		BtreeIndexFile btreeFile = btreeFiles.get(name);
		if(btreeFile == null){
			btreeFile = dbFs.openBtreeIndexFile(name);
		}
		BTree<T, Id> btee = FileBTree.getOrCreate(btreeFile, 10, new ObjectPerst<T>(), new IdPerst());
		FileBtreeIndex<T> index = new FileBtreeIndex<T>(btee, txManager, statusManager, lockManager);
		
		return index;
	}
	
	
	public void runMaintenance() {
		
	}

	
}
